package socket;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 聊天室的客户端
 *   V3版的客户端start方法中的主要逻辑是先等待用户在控制台上输入一行字符串,然后将其发送给服务端后再读取
 *  来自服务端发送过来的消息.
 *  但是由于V4服务器已经改成了可以将其他客户端的消息也转发给所有有客户端的操作,这会导致有源源不断的新消息
 *  发送给客户端,然后如果客户端必须先等待用户输入一行再接收一行来自服务端消息的话,会导致接收消息不畅问题.
 *
 *  为了解决这个问题:
 *  我们应当将发送消息和接收消息的操作分别在不同的线程上运行,才能做到互不干涉.
 *
 * 实现:
 *  我们将发送消息还定义在start方法中由客户端的主线程执行即可,将读取消息单独定义到一个线程上执行
 *  1:定义内部类ServerHandler,这是一个线程任务,主要工作就是读取来自服务端发送的消息并输出到客户端的
 * 控制台上
 *  2:在start方法一开始就启动一个线程来执行ServerHandler这个任务,不断接收来自服务端的消息.
 *
 */
public class Client4 {
    private Socket socket;
    public Client4(){
        //实例化Socket时就是与远程服务器建立连接的过程
        //需要传递两个参数:
        //1.服务器的IP地址，用于找到网络上对方的计算机
        //2.服务端口，用于找到服务器计算机上的服务端的应用程序(软件)
        //176.28.2.17
        try {
            System.out.println("正在连接服务器...");
            socket = new Socket("176.28.2.17",8088);//localhost表示本机IP
            System.out.println("与服务器建立连接成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void start(){
        try {
            //V4:启动用于接收服务端消息的线程
            ServerHandler handler = new ServerHandler();
            Thread t = new Thread(handler);
            t.start();

            //低级流，作用:将写出的字节发送给建立连接的远程计算机
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw,true);//自动行刷新


            Scanner scan = new Scanner(System.in);
            System.out.println("请输入你的用户名");
            String name = scan.nextLine();
            while (true){
                String line = scan.nextLine();
                if ("退出".equals(line)){
                    break;
                }
                if ("exit".equals(line)){
                    break;
                }
                pw.println(name+"说:"+line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                socket.close();//与服务器断开连接
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Client4 client = new Client4();
        client.start();
    }

    /**
     * V4:该线程任务是负责不断接收来自服务端发送过来的消息并输出到控制台
     */
    private class ServerHandler implements Runnable{
        public void run(){
            try {
                //V3:通过socket获取输入流用于读取来自服务端发送过来的消息
                InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in,StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);

                String line;
                while ((line=br.readLine())!=null){
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
